﻿using System.Collections.Generic;

namespace iTool.PluginCore.Connector
{
    public interface IRouteTemplatePatternCreator
    {
        RouteTemplate Create(string originalTemplate);
    }

    public class RouteTemplatePatternCreator : IRouteTemplatePatternCreator
    {
        private const string RegExMatchOneOrMoreOfEverything = ".+";
        private const string RegExMatchOneOrMoreOfEverythingUntilNextForwardSlash = "[^/]+";
        private const string RegExMatchEndString = "$";
        private const string RegExIgnoreCase = "(?i)";
        private const string RegExForwardSlashOnly = "^/$";
        private const string RegExForwardSlashAndOnePlaceHolder = "^/.*";

        public RouteTemplate Create(string originalTemplate)
        {
            string inputTemplate = originalTemplate;

            var placeholders = new List<string>();

            for (var i = 0; i < inputTemplate.Length; i++)
            {
                if (IsPlaceHolder(inputTemplate, i))
                {
                    var postitionOfPlaceHolderClosingBracket = inputTemplate.IndexOf('}', i);
                    var difference = postitionOfPlaceHolderClosingBracket - i + 1;
                    var placeHolderName = inputTemplate.Substring(i, difference);
                    placeholders.Add(placeHolderName);

                    //hack to handle /{url} case
                    if (ForwardSlashAndOnePlaceHolder(inputTemplate, placeholders, postitionOfPlaceHolderClosingBracket))
                    {
                        return new RouteTemplate(RegExForwardSlashAndOnePlaceHolder, false, originalTemplate);
                    }
                }
            }

            var containsQueryString = false;

            if (inputTemplate.Contains("?"))
            {
                containsQueryString = true;
                inputTemplate = inputTemplate.Replace("?", "\\?");
            }

            for (int i = 0; i < placeholders.Count; i++)
            {
                var indexOfPlaceholder = inputTemplate.IndexOf(placeholders[i]);
                var indexOfNextForwardSlash = inputTemplate.IndexOf("/", indexOfPlaceholder);
                if (indexOfNextForwardSlash < indexOfPlaceholder || (containsQueryString && inputTemplate.IndexOf("?") < inputTemplate.IndexOf(placeholders[i])))
                {
                    inputTemplate = inputTemplate.Replace(placeholders[i], RegExMatchOneOrMoreOfEverything);
                }
                else
                {
                    inputTemplate = inputTemplate.Replace(placeholders[i], RegExMatchOneOrMoreOfEverythingUntilNextForwardSlash);
                }
            }

            if (inputTemplate == "/")
            {
                return new RouteTemplate(RegExForwardSlashOnly, containsQueryString, originalTemplate);
            }

            if (inputTemplate.EndsWith("/"))
            {
                inputTemplate = inputTemplate.Remove(inputTemplate.Length - 1, 1) + "(/|)";
            }

            // 区别大小写
            var template = false //route.RouteIsCaseSensitive
                ? $"^{inputTemplate}{RegExMatchEndString}"
                : $"^{RegExIgnoreCase}{inputTemplate}{RegExMatchEndString}";

            return new RouteTemplate(template, containsQueryString, originalTemplate);
        }

        private bool ForwardSlashAndOnePlaceHolder(string inputTemplate, List<string> placeholders, int postitionOfPlaceHolderClosingBracket)
        {
            if (inputTemplate.Substring(0, 2) == "/{" && placeholders.Count == 1 && inputTemplate.Length == postitionOfPlaceHolderClosingBracket + 1)
            {
                return true;
            }

            return false;
        }

        private bool IsPlaceHolder(string inputTemplate, int i)
        {
            return inputTemplate[i] == '{';
        }

    }
}
